package com.lx.bbs.controller;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lx.bbs.entity.BizException;
import com.lx.bbs.entity.Result;
import com.lx.bbs.entity.User;
import com.lx.bbs.entity.UserEX;
import com.lx.bbs.service.IUserService;
import com.lx.bbs.service.MailBiz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.Jedis;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * BBS论坛-用户表-6 前端控制器
 * </p>
 *
 * @author lx
 * @since 2024-11-23
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    IUserService userService;

    @PostMapping("login")
    public Result login(@Valid User user, Errors errors, HttpSession session, HttpServletResponse response) throws BizException {
        // Errors 是mybatis的错误集, 用于收集mapper映射里面的报错信息, 可以手动加入报错信息
        if (errors.hasFieldErrors("uname") || errors.hasFieldErrors("upass")) {
            throw new BizException("", errors.getAllErrors());
        }
        try( Jedis jedis = new Jedis("localhost", 7000); ){
            User dbUser = userService.login(user);
            session.setAttribute("myinfo", dbUser);
            String requestURL = (String) session.getAttribute("RequestURL");
            session.removeAttribute("RequestURL");
            // 把登录记录存入redis
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

            String key = simpleDateFormat.format(new Date()).toString();
            jedis.setbit(key, Long.parseLong(String.valueOf(dbUser.getId())), true);
            // 判断是否是活跃用户
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            String day2 = simpleDateFormat.format(calendar.getTime());
            calendar.add(Calendar.DAY_OF_MONTH, -2);
            String day3 = simpleDateFormat.format(calendar.getTime());

            if (jedis.getbit(key, Long.parseLong(String.valueOf(dbUser.getId()))) &&
                    jedis.getbit(day2, Long.parseLong(String.valueOf(dbUser.getId()))) &&
                    jedis.getbit(day3, Long.parseLong(String.valueOf(dbUser.getId())))) {
                dbUser.setActive(true);
            }else{
                dbUser.setActive(false);
            }
            dbUser.setRequestURL(requestURL);
            this.getAutoTime(user, response);
            return new Result(1, "登陆成功", dbUser);
        }catch (BizException e){
            // 添加自定义的错误信息
            errors.rejectValue( "uname", "uname or upass error", e.getMessage());
            // 给业务异常添加错误
            e.setData(errors.getAllErrors());
            throw e;
        }

    }

    @RequestMapping("myinfo")
    public Result myinfo(@SessionAttribute(required = false) User myinfo,
                         @CookieValue(required = false) String uname,
                         @CookieValue(required = false) String upass,
                         HttpSession session) throws BizException {
        if(myinfo == null){
            if(uname == null || upass == null){
                throw new BizException("未登录", null);
            }else{
                LambdaUpdateWrapper<User> lqw = new LambdaUpdateWrapper<>();
                lqw.eq(User::getUname, uname);
                lqw.eq(User::getUpass, upass);
                myinfo = userService.getOne(lqw);
                session.setAttribute("myinfo", myinfo);
            }
        }
        return new Result(1, "已登录", myinfo);
    }

    @RequestMapping("logout")
    public ModelAndView logout(User user, HttpSession session, ModelAndView mav, HttpServletResponse response) throws BizException {
        Cookie cookie = new Cookie("uname", user.getUname());
        Cookie cookie1 = new Cookie("upass", user.getUpass());

        cookie.setPath("/");
        cookie1.setPath("/");
        // '删除' cookie
        cookie.setMaxAge(0);
        cookie1.setMaxAge(0);
        session.invalidate(); // 会话失效
        mav.setViewName("redirect:/index.html");
        response.addCookie(cookie);
        response.addCookie(cookie1);
        return mav;
    }

    @PostMapping("upload")
    @ResponseBody
    public Result uploadHead(@RequestParam("head") MultipartFile file) throws IOException {
        // 获取上传的文件名
        String filename = file.getOriginalFilename();
        String prefix = UUID.randomUUID().toString();
        String suffix = filename.replaceFirst(".+ /.( /w+)", "$1");
        filename = prefix + "." + suffix;
        file.transferTo(new File("D:/upload/" + filename));
        String webPath = "image/head/" + filename;
        return new Result(1,"文件上传成功", webPath);
    }

    @RequestMapping("reg")
    public Result reg(@Valid UserEX user, Errors errors) throws BizException {
        userService.reg(user, errors);
        return new Result(1, "注册成功", null);
    }

    @RequestMapping("question")
    public Result uploadQuestion(User user, Errors errors) throws BizException {
        userService.uploadQuestion(user, errors);
        return new Result(1, "添加成功", null);
    }

    @RequestMapping("getQuestion")
    public Result getQuestion() throws BizException {
        User question = userService.getQuestion();
        return new Result(1, null, question);
    }

    @RequestMapping("getAutoTime")
    public void getAutoTime(User user, HttpServletResponse response) throws BizException {
       Cookie cookie = new Cookie("uname", user.getUname());
        Cookie cookie2 = new Cookie("upass", user.getUpass());
        cookie.setPath("/");
        cookie2.setPath("/");
        switch (user.getAutoTime()){
            case 1:
                cookie.setMaxAge(24*60*60);
                cookie2.setMaxAge(24*60*60);
                break;
            case 2:
                cookie.setMaxAge(7*24*60*60);
                cookie2.setMaxAge(7*24*60*60);
                break;
            case 3:
                cookie.setMaxAge(30*24*60*60);
                cookie2.setMaxAge(30*24*60*60);
                break;
            default:
                return;
        }
        response.addCookie(cookie);
        response.addCookie(cookie2);
    }

    @Autowired
    MailBiz mailBiz;

    @RequestMapping("forgetPwd")
    public Result forgetPwd(String uname, HttpSession session){
        LambdaUpdateWrapper<User> lqw = new LambdaUpdateWrapper<>();
        lqw.eq(User::getUname, uname);
        User user = userService.getOne(lqw);
        if (user == null) {
            return new Result(-1, "没有该用户账号", null);
        }
        String msg = "验证码为: ";
        // 时间挫
        String vcode = System.currentTimeMillis()+"";
        vcode = vcode.substring(vcode.length() - 4);
        msg += vcode;
        session.setAttribute("forgetVcode", vcode);
        session.setAttribute("forgetUser", user);
        mailBiz.sendSimpleMail("忘记密码的验证", "3261810649@qq.com", user.getEmail(), msg);
        // TODO 部分隐藏邮箱
        // TODO 验证码设置时效
        String prefix = user.getEmail().substring(0, 3);
        String replace = user.getEmail().replaceAll("[a-zA-Z0-9]+@", "******");
        String Email = prefix + replace;
        // TODO vcode的有效期 三分钟有效  定时任务 Task
        // java自带的java.util.Timer类 该类允许你调用一个java.util.TimerTask任务
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                session.removeAttribute("forgetVcode");
            }
        };
        // task-所安排的任务  time-执行任务的时间 在时间等于或者超过time的时候执行且仅执行一次
        Timer timer = new Timer();
        timer.schedule(task, 18000); //180s

        return new Result(1, "验证码已经发送到你的"+Email+"邮箱, 验证码在三分钟后过期", null);
    }

    @RequestMapping("reSetPwd")
    public Result reSetPwd(String vcode, String pwd, String repwd,
                           @SessionAttribute User forgetUser,
                           HttpSession session){
        // @SessionAttribute String forgetVcode 如果 forgetVcode 失效, 会导致报400错
        String forgetVcode = (String) session.getAttribute("forgetVcode");
        if ( forgetVcode== null) {
            return new Result(-1, "验证码已经失效或未发送", null);
        }else if(!vcode.equalsIgnoreCase(forgetVcode)){
            return new Result(-2, "验证码错误", null);
        }else if(!pwd.equals(repwd)){
            return new Result(-3, "两次密码不一致", null);
        }else if(pwd.equals("") || repwd.equals("")){
            return new Result(-4, "密码不能为空", null);
        }else if(vcode.equals("")){
            return new Result(-5, "验证码不能为空", null);
        }
        LambdaUpdateWrapper<User> lqw = new LambdaUpdateWrapper<>();
        lqw.eq(User::getId, forgetUser.getId());
        forgetUser.setUpass(pwd);
        userService.saveOrUpdate(forgetUser);
        session.removeAttribute("forgetVcode");
        session.removeAttribute("forgetUser");
        return new Result(1, "密码重置成功", null);
    }
}

